package org.example.database_course_design.service.impl;

import cn.hutool.system.UserInfo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.opencsv.CSVWriter;
import org.example.database_course_design.entity.PO.Cardinfo;
import org.example.database_course_design.entity.PO.Deposit;
import org.example.database_course_design.entity.PO.Tradeinfo;
import org.example.database_course_design.entity.PO.Userinfo;
import org.example.database_course_design.mapper.CardinfoMapper;
import org.example.database_course_design.mapper.DepositMapper;
import org.example.database_course_design.mapper.TradeinfoMapper;
import org.example.database_course_design.mapper.UserinfoMapper;
import org.example.database_course_design.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

@Service
public class AdminServiceImpl implements AdminService {
    @Autowired
    private CardinfoMapper cardinfoMapper;

    @Autowired
    private DepositMapper depositMapper;

    @Autowired
    private TradeinfoMapper tradeinfoMapper;

    @Autowired
    private UserinfoMapper userinfoMapper;

    @Override
    public Userinfo login(String username, String password) {
        if(username.compareTo("admin") == 0 && password.compareTo("admin") == 0) return new Userinfo().setCustomerName("管理员").setCustomerID(0l);
        return null;
    }

    @Override
    public Boolean removeById(String pid) {
        int num = userinfoMapper.delete(new QueryWrapper<Userinfo>().eq("PID", pid));
        return num == 1;
    }

    @Override
    public Userinfo update(Userinfo userinfo) {
        System.out.println(userinfo);
        int num = userinfoMapper.update(userinfo, new QueryWrapper<Userinfo>().eq("PID", userinfo.getPid()));
        return num == 1? userinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("PID", userinfo.getPid())) : null;
    }

    @Override
    public Userinfo signup(Map<String, Object> map) {
        Userinfo u = new Userinfo();
        u.setPid((String) map.getOrDefault("Pid", null));
        u.setCustomerName((String) map.getOrDefault("CustomerName", null));
        u.setTelephone((String) map.getOrDefault("Telephone", null));
        u.setAddress((String) map.getOrDefault("Address", null));
        if(userinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("PID", u.getPid())) != null)
            return null;
        int num = userinfoMapper.insert(u);
        return num == 1? userinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("PID", u.getPid())) : null;
    }

    @Override
    public Page<Userinfo> getCustomerList(Integer pageNum, Integer pageSize) {
        Page<Userinfo> page = new Page(pageNum, pageSize);
        return userinfoMapper.selectPage(page, new QueryWrapper<>());
    }

    @Override
    public void CustomerToCSV(String path) throws IOException {
        List<Userinfo> users = userinfoMapper.selectList(new QueryWrapper<>());
        CSVWriter writer = new CSVWriter(new FileWriter(path, StandardCharsets.UTF_8));

        writer.writeNext(new String[]{"customerID", "customerName", "PID", "telephone", "address"});
        for (Userinfo user : users) {
            writer.writeNext(new String[]{
                    String.valueOf(user.getCustomerID()),
                    user.getCustomerName(),
                    user.getPid(),
                    user.getTelephone(),
                    user.getAddress()
            });
        }
        writer.close();
    }

    @Override
    public List<Cardinfo> addCard(String pass, String pid, BigDecimal openMoney) {
        Userinfo u = userinfoMapper.selectOne(new QueryWrapper<Userinfo>().eq("PID", pid));
        if(u == null) return null;
        
        // 生成新的卡号（格式：10103576 + 8位随机数）
        String cardNumber = generateUniqueCardNumber();
        
        Cardinfo cardinfo = new Cardinfo();
        cardinfo.setCardID(cardNumber); // 使用生成的卡号
        cardinfo.setPass(pass);
        cardinfo.setBalance(openMoney);
        cardinfo.setCustomerID(u.getCustomerID());
        cardinfo.setOpenMoney(openMoney);
        cardinfo.setCurID("RMB"); // 默认币种
        cardinfo.setSavingID(1); // 默认存款类型为活期
        cardinfo.setIsReportLoss("否"); // 默认未挂失
        
        cardinfoMapper.insert(cardinfo);
        return cardinfoMapper.selectList(new QueryWrapper<Cardinfo>().eq("customerID", u.getCustomerID()));
    }
    
    /**
     * 生成唯一的卡号
     * @return 生成的卡号
     */
    private String generateUniqueCardNumber() {
        String cardNumber;
        int attempts = 0;
        do {
            // 生成8位随机数
            int randomNum = (int) (Math.random() * 100000000);
            cardNumber = String.format("10103576%08d", randomNum);
            attempts++;
            
            // 检查卡号是否已存在
            Cardinfo existingCard = cardinfoMapper.selectOne(new QueryWrapper<Cardinfo>().eq("cardID", cardNumber));
            if (existingCard == null) {
                return cardNumber;
            }
        } while (attempts < 10); // 最多尝试10次
        
        // 如果10次都失败，抛出异常
        throw new RuntimeException("无法生成唯一的卡号，请稍后重试");
    }

    @Override
    public Page<Cardinfo> getCardList(Integer pageNum, Integer pageSize) {
        return cardinfoMapper.selectPage(new Page<>(pageNum, pageSize), new QueryWrapper<>());
    }

    @Override
    public Boolean updateCard(Cardinfo c) {
        int num = cardinfoMapper.updateById(c);
        return num == 1;
    }

    @Override
    public Boolean deleteCard(String cardID, String password) {
        int num = cardinfoMapper.delete(new QueryWrapper<Cardinfo>().eq("cardID", cardID).eq("pass", password));
        return num == 1;
    }

    @Override
    public void CardToCSV(String path) throws IOException {
        List<Cardinfo> cardinfos = cardinfoMapper.selectList(new QueryWrapper<>());
        CSVWriter writer = new CSVWriter(new FileWriter(path, StandardCharsets.UTF_8));

        writer.writeNext(new String[]{"CardID", "CurID", "IsReportLoss", "Balance", "CustomerID", "OpenDate", "OpenMoney"});
        for (Cardinfo cardinfo : cardinfos) {
            writer.writeNext(new String[]{
                    cardinfo.getCardID(),
                    cardinfo.getCurID(),
                    cardinfo.getIsReportLoss(),
                    String.valueOf(cardinfo.getBalance()),
                    String.valueOf(cardinfo.getCustomerID()),
                    String.valueOf(cardinfo.getOpenDate()),
                    String.valueOf(cardinfo.getOpenMoney()),
            });
        }
        writer.close();
    }

    @Override
    public Page<Tradeinfo> getTradeList(Integer nums, Integer size) {
        return tradeinfoMapper.selectPage(new Page<>(nums, size), new QueryWrapper<>());
    }

    @Override
    public Boolean deleteTrade(Integer tradeID) {
        return tradeinfoMapper.deleteById(tradeID) == 1;
    }

    @Override
    public void TradeToCSV(String path) throws IOException {
        List<Tradeinfo> tradeinfos = tradeinfoMapper.selectList(new QueryWrapper<>());
        CSVWriter writer = new CSVWriter(new FileWriter(path, StandardCharsets.UTF_8));

        writer.writeNext(new String[]{"CardID", "TradeID", "TradeType", "Remark", "TradeDate", "TradeMoney"});
        for (Tradeinfo tradeinfo : tradeinfos) {
            writer.writeNext(new String[]{
                    tradeinfo.getCardID(),
                    String.valueOf(tradeinfo.getTradeID()),
                    tradeinfo.getTradeType(),
                    tradeinfo.getRemark(),
                    String.valueOf(tradeinfo.getTradeDate()),
                    String.valueOf(tradeinfo.getTradeMoney())
            });
        }
        writer.close();
    }

    @Override
    public Deposit addDeposit(Deposit deposit) {
        Deposit deposit1 = depositMapper.selectOne(new QueryWrapper<Deposit>().eq("SavingName", deposit.getSavingName()));
        if(deposit1 == null) {
            depositMapper.insert(deposit);
            return deposit;
        }
        return null;
    }

    @Override
    public Page<Deposit> getDepositList(Integer nums, Integer size) {
        return depositMapper.selectPage(new Page<>(nums, size), new QueryWrapper<>());
    }

    @Override
    public Boolean updateDeposit(Deposit deposit) {
        return depositMapper.updateById(deposit) == 1;
    }

    @Override
    public Boolean deleteDeposit(Long savingID) {
        return depositMapper.deleteById(savingID) == 1;
    }

    @Override
    public void DepositToCSV(String path) throws IOException {
        List<Deposit> deposits = depositMapper.selectList(new QueryWrapper<>());
        CSVWriter writer = new CSVWriter(new FileWriter(path, StandardCharsets.UTF_8));
        writer.writeNext(new String[]{"SavingID", "SavingName", "Descrip"});
        for (Deposit deposit : deposits) {
            writer.writeNext(new String[]{
                    String.valueOf(deposit.getSavingID()),
                    deposit.getSavingName(),
                    deposit.getDescrip(),
            });
        }
        writer.close();
    }
}
